package com.peaksport.framework.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import com.peaksport.framework.exception.PKBizException;
import com.peaksport.framework.exception.PKDevException;

public class PKPublicUtils {
		
	/** 常用数值*/
	public static final BigDecimal BIGDECIMAL0 = BigDecimal.ZERO;
	public static final BigDecimal BIGDECIMAL100 = new BigDecimal(100.00);
	public static final BigDecimal BIGDECIMAL1 = BigDecimal.ONE;
	
	/** 日期格式*/
	public static final SimpleDateFormat SDF_YYYY = new SimpleDateFormat("yyyy");
	public static final SimpleDateFormat SDF_YYYYMM = new SimpleDateFormat("yyyy-MM");
	public static final SimpleDateFormat SDF_YYYYMMDD = new SimpleDateFormat("yyyy-MM-dd");
	public static final SimpleDateFormat SDF_YYYYMMDD_HHMMSS = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	public static final SimpleDateFormat SDF_YYYYMMDD_HHMMSS_E = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss E");
	public static final SimpleDateFormat SDF_MM = new SimpleDateFormat("MM");
	public static final SimpleDateFormat SDF_DD = new SimpleDateFormat("dd");
	public static final SimpleDateFormat SDF_TIME = new SimpleDateFormat("HH:mm:ss");

	/** 数字格式*/
	public static final DecimalFormat DECF_10 = new DecimalFormat("#.##########");
	
	/** 回车换行  **/
	public static final String CR = "\r\n";
	/** 冒号 */
	public static final String COLON = ":";
	/** 空格  */
	public static final String SPACE = " ";
	/** 逗号 */
	public static final String COMMA = ",";
	/** 引号 */
	public static final String QUOTE = "'";
	/** #号 */
	public static final String POUND_SIGN = "#";

	/**
	 * 比较两个对象是否一样
	 * @param obj1
	 * @param obj2
	 * @return
	 */
	public static boolean equals(Object obj1, Object obj2) {
		if ((obj1 == null) && (obj2 == null))
			return true;
		else if (((obj1 == null) && (obj2 != null)) || ((obj1 != null) && (obj2 == null)))
			return false;
		else if ((obj1 != null) && (obj2 != null)) {
			if (obj1 instanceof java.sql.Date)
				obj1 = new java.util.Date(((java.sql.Date) obj1).getTime());
			if (obj2 instanceof java.sql.Date)
				obj2 = new java.util.Date(((java.sql.Date) obj2).getTime());
			String className1 = obj1.getClass().getName();
			String className2 = obj2.getClass().getName();

			if (!(className1.equals(className2))) {
				StringBuffer errmsg = new StringBuffer();
				errmsg.append("比较函数使用错误,比较对象不是同一种类型:")
				.append(String.format("参数1(type=[%s],value=[%s])",className1,obj1.toString()))
				.append(String.format("参数2(type=[%s],value=[%s])",className2,obj2.toString()));
				throw new PKDevException(errmsg.toString());
			}
			if (obj1 instanceof BigDecimal) {
				obj1 = ((BigDecimal) obj1).setScale(6, 4);
				obj2 = ((BigDecimal) obj2).setScale(6, 4);
				return (((BigDecimal) obj1).compareTo((BigDecimal) obj2) == 0);
			}
			return obj1.equals(obj2);
		} else return false;
		
	}
	
	/**
	 * 比较是否与其中任何一个相等
	 * @param obj1
	 * @param objs
	 * @return
	 */
	public static boolean equalsAny(Object obj1, Object... objs) {
		for (Object obj2 : objs) {
			boolean b = equals(obj1, obj2);
			if (b) return b;
		}
		return false;
	}
	
	/**
	 *  忽略大小写比较是否相等
	 * @param str1
	 * @param str2
	 * @return
	 */
	public static boolean equalsIgnoreCase(String str1, String str2) {
		if (str1 != null) str1 =str1.toLowerCase();
		if (str2 != null) str2 = str2.toLowerCase();
		return equals(str1, str2);
	}
	
	/**
	 * 
	 * 忽略大小写比较是否与其中一个相等
	 * @param str1
	 * @param strs
	 * @return
	 */
	public static boolean equalsIgnoreCaseAny(String str1, String... strs) {
		if (str1 != null) str1 = str1.toLowerCase();
		for (String str2: strs) {
			if (str2 != null) str2 = str2.toLowerCase();
			boolean b = equals(str1, str2);
			if (b) return b;
		}
		return false;
	}

	
	public static boolean isEmpty(List<?> lst) {
		return ((lst == null) || (lst.isEmpty()));
	}

	
	public static boolean isEmpty(Set<?> set) {
		return ((set == null) || (set.isEmpty()));
	}

	
	public static boolean isEmpty(Map<?, ?> map) {
		return ((map == null) || (map.isEmpty()));
	}

	public static boolean isEmpty(String str) {
		return ((str == null) || ("".equals(str)));
	}

	/**
	 * 字符串str是否包含在字符串队列searchStr里(字符数队列searchStr是否存在一个str里字符)
	 * @param str 字符串
	 * @param searchStr 待搜索字符串队列
	 * @return
	 */
	public static boolean contains(String str, String... searchStr) {
		if ((searchStr == null) || (searchStr.length == 0))
			return false;
		if (str == null)
			return false;
		for (String s : searchStr) {
			boolean b = equals(str,s);
			if (b)
				return b;
		}
		return false;
	}

	public static String[] setToString(Set<String> set) {
		if ((set == null) || (set.isEmpty()))
			return null;
		String[] str = new String[set.size()];
		set.toArray(str);
		return str;
	}

	public static Integer[] setToInteger(Set<Integer> set) {
		if ((set == null) || (set.isEmpty()))
			return null;
		Integer[] i = new Integer[set.size()];
		set.toArray(i);
		return i;
	}

	public static String[] vectorToString(Vector<String> vec) {
		if ((vec == null) || (vec.isEmpty()))
			return null;
		String[] str = new String[vec.size()];
		vec.toArray(str);
		return str;
	}

	public static Integer[] vectorToInteger(Vector<Integer> vec) {
		if ((vec == null) || (vec.isEmpty()))
			return null;
		Integer[] i = new Integer[vec.size()];
		vec.toArray(i);
		return i;
	}

	public static String[] hashKeyToArray(Map<String, ?> hash) {
		if ((hash == null) || (hash.isEmpty()))
			return null;
		Set<String> set = hash.keySet();
		return setToString(set);
	}

	public static String getStackTrace(Throwable t) {
		StringWriter sw = new StringWriter();
		PrintWriter pw = new PrintWriter(sw, true);
		t.printStackTrace(pw);
		pw.flush();
		sw.flush();
		return sw.toString();
	}

	public static boolean isDate(Object value) {
		if (value == null)
			return false;
		if (value instanceof String) {
			try {
				new SimpleDateFormat().parse(value.toString());
				return true;
			} catch (Exception e) {
				return false;
			}
		}
		return (value instanceof java.util.Date);
	}

	public static BigDecimal getBigDecimal(Object value, int scale) {
		BigDecimal returnValue = getBigDecimal(value);
		returnValue.setScale(scale, BigDecimal.ROUND_HALF_UP);
		return returnValue;
	}

	public static BigDecimal getBigDecimal(Object value){
		if (value == null)
			return BIGDECIMAL0;
		else if (value instanceof BigDecimal)
			return ((BigDecimal) value);
		else if (value instanceof String)
			return new BigDecimal((String) value);
		else if (value instanceof Double)
			return new BigDecimal(((Double) value).doubleValue());
		else if (value instanceof Integer)
			return new BigDecimal(((Integer) value).intValue());
		else {
			String msg = String.format("getBigDecimal参数类型[%s]异常", new Object[] { value.getClass().getName() });
			throw new PKDevException(msg);
		}
	}

	/**
     * 值转换为布尔型，并判断是否为真
     * @param value
     * @return
     */
	public static boolean isTrue(String value) {
		if (isEmpty(value))
			return false;
		if (equals("1", value))
			return true;
		return (equals("true", value.toLowerCase()));
	}

	/**
     * 值转换为布尔型，并判断是否为真
     * @param value
     * @return
     */
	public static boolean isTrue(int value) {
		return (1 == value);
	}

	/**
	 *  是否为0值,null视为0值
	 * @param value
	 * @return
	 * @throws Exception
	 */
	public static boolean isZero(BigDecimal value) throws Exception {
		return (BIGDECIMAL0.compareTo(getBigDecimal(value)) == 0);
	}

	/**
	 * 判断空值
	 * 
	 * @param obj
	 * @param formatStr
	 * @param args
	 */
	public static void verifyBizNull(Object obj, String formatStr,Object... args) {
		if (obj == null) {
			String errmsg = String.format(formatStr, args);
			throw new PKBizException(errmsg);
		}
	}
	
	/**
     * 是否中文(包含中文标点符号)
     * @param c
     * @return
     */
	public static boolean isChineseCharacter(char c) {
		Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
		return ((ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS)
				|| (ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS)
				|| (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A)
				|| (ub == Character.UnicodeBlock.GENERAL_PUNCTUATION)
				|| (ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION)
				|| (ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS));
	}
	
	/**
	 * 对象克隆
	 * @param obj
	 * @return
     */
	public static Object clone(Object obj) {
		try {
			if (!Serializable.class.isAssignableFrom(obj.getClass())) {
				throw new CloneNotSupportedException();
			}
			ByteArrayOutputStream baOut = new ByteArrayOutputStream();
			ObjectOutputStream objOut = new ObjectOutputStream(baOut);
			objOut.writeObject(obj);
			ByteArrayInputStream baIn = new ByteArrayInputStream(baOut.toByteArray());
			ObjectInputStream objIn = new ObjectInputStream(baIn);
			return objIn.readObject();
		} catch (Exception exc) {
			throw new PKDevException(exc);
		}
	}
	
	/**
	 * Object 转 字节
	 * @param obj
	 * @return
	 */
	public static byte[] objectToBytes(Object obj){
        byte[] bytes = null;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ObjectOutputStream sOut;
        try {
            sOut = new ObjectOutputStream(out);
            sOut.writeObject(obj);
            sOut.flush();
            bytes= out.toByteArray();
        } catch (Exception exc) {
        	throw new PKDevException(exc);
        }
        return bytes;
    }

	/**
	 * 字节转Object
	 * @param bytes
	 * @return
	 */
    public static Object bytesToObject(byte[] bytes) {
    	Object obj;
        ByteArrayInputStream in = new ByteArrayInputStream(bytes);
        ObjectInputStream sIn;
        try {
            sIn = new ObjectInputStream(in);
           obj = sIn.readObject();
        } catch (Exception exc) {
        	throw new PKDevException(exc);
        }
        return obj;

    }

}
